/**
  ETFDAQ Project
  \class TAMesytec
  \brief A VME card produced by Mesytec Corp. from Germany
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2024-09-05
  \date 2024-09-05 last modified

  \copyright Copyright (c) 2024 IMP-CAS with LGPLv3 LICENSE
*/

#ifndef TAMesytec_h
#define TAMesytec_h

#include "TACard.h"

class TAMesytec : public TACard{
public:
  TAMesytec(TAController *ctrl, const TAYaml &c);
  virtual ~TAMesytec();

  ///--- initialization ---///
  virtual void Initialize() override; ///< config the card
  virtual void Identify() override; ///< read card info (e.g. serialNo.)
  virtual void SlotInit() override; ///< write slot id and crate id
  /// \param level 1~7, 0 will disable the IRQ generation
  /// \param vector 0x00~0xFF, requested by vme ctrler to identify the interrupter
  /// \param n: trigger will be generated after nof buffered events
  /// (or data words, depending on \sa isEv) reaches n
  /// \param isEv: whether use event or data trigger
  virtual void ConfigIRQ(int level, int vector, int n, bool isEv) const;
  using TACard::ConfigIRQ;
  /// change the header to be compatible with CAEN cards
  /// 1. move module id [16:20] to [27:31]
  /// 2. leave [26] to 0, and move hsig [30:31] to [24:25]
  /// 3. move [0:15] (nw+res) to [8:23]
  /// 4. set [0:7] to 0 permanently
  void ModifyHeader(uint32_t &h);

  ///--- configuration ---///
  /// data reset(DR), software reset(SR) and hardware reset(HR) are different
  /// Please refer to the register map to check what they resets respectively
  /// usually DR only resets data, ev counters and read/write pointers
  /// SR is DR plus reset of most of the controlling registers
  /// HR is SR plus all the resetable registers
  virtual void SoftwareReset() override;

  ///--- the DAQ loop ---///
  virtual bool DataReady() const override; ///< true if buffered events are enough
  /// read all events in the buffer \retval nof words read
  virtual int ReadData(uint32_t *buf) override;
  /// read 1 event \retval nof words read
  virtual int ReadEvent(uint32_t *buf) override;
  /// clear the module's multi-event buffers, the R/W pointers, and the event counters
  virtual void ClearData() override; // data reset (DR)
  virtual void ClearEventCounter() override; // clears the event counter
  virtual void ResetForNewRun() override;

  /// ---- print functions ---///
  virtual void Print() const override;
  virtual void PrintEvent(const uint32_t *ev)  override;
  /// \return the event counter register
  virtual void ReadEventCounter() override;

  /// pure virtual as we need costomized error tips
  virtual void SetResolution(uint16_t res) = 0;

protected:
  uint16_t fRes; ///< resolution
  double fBlip; ///< LSB in ps (TDC) or mV (ADC)
  // nof words in the buffer
  uint16_t fDataLen; ///< in the unit specified by fDataLenFormat
  ///< bank0 (0-15) and bank1 (16-31) operate independently
  uint16_t fBankOp; // 0: false; 1: true; 3: other use (see madc32)
  uint16_t fDataLenFormat; // 0-1-2-3: D8-16-32-MBLT64 for VME read
};

#endif
